package com.xuexiang.xui_lib.component.progress.loading;

import ohos.agp.animation.Animator;
import ohos.agp.animation.AnimatorValue;
import ohos.agp.components.AttrHelper;
import ohos.agp.components.AttrSet;
import ohos.agp.components.Component;
import ohos.agp.render.Canvas;
import ohos.agp.render.Paint;
import ohos.agp.utils.Color;
import ohos.agp.utils.Point;
import ohos.agp.utils.RectFloat;
import ohos.app.Context;
import ohos.hiviewdfx.HiLog;
import ohos.hiviewdfx.HiLogLabel;

public class MiniLoadingView extends Component implements Component.BindStateChangedListener {
    private static final HiLogLabel LABEL = new HiLogLabel(HiLog.LOG_APP, 0x00205, "MiniLoadingView");
    private int mSize;
    private Color mPaintColor;
    private int mAnimateValue = 0;
    private AnimatorValue mAnimator;
    private Paint mPaint;
    private static final int LINE_COUNT = 12;
    private static final int DEGREE_PER_LINE = 360 / LINE_COUNT;

    public MiniLoadingView(Context context) {
        super(context);
        initAttrs(context, null);
    }

    public MiniLoadingView(Context context, AttrSet attrSet) {
        super(context, attrSet);
        setBindStateChangedListener(this);
        initAttrs(context, attrSet);
    }

    public MiniLoadingView(Context context, AttrSet attrSet, String styleName) {
        super(context, attrSet, styleName);
        setBindStateChangedListener(this);
        initAttrs(context, attrSet);
    }

    public MiniLoadingView(Context context, int size, Color color) {
        super(context);
        mSize = size;
        mPaintColor = color;
        initAttrs(context, null);
    }

    private void initAttrs(Context context, AttrSet attrs) {
        if (attrs != null) {
            if (attrs.getAttr("mlv_loading_view_size").isPresent()) {
                mSize = AttrHelper.vp2px(attrs.getAttr("mlv_loading_view_size").get().getIntegerValue(), getContext());
            } else {
                mSize = AttrHelper.vp2px(24, getContext());
            }

            if (attrs.getAttr("mlv_loading_view_color").isPresent()) {
                mPaintColor = attrs.getAttr("mlv_loading_view_color").get().getColorValue();
            } else {
                mPaintColor = Color.BLACK;
            }
        } else {
            mSize = AttrHelper.vp2px(24, getContext());
            mPaintColor = Color.BLACK;
        }

        initPaint();
        setEstimateSizeListener(new EstimateSizeListener() {
            @Override
            public boolean onEstimateSize(int widthEstimateConfig, int heightEstimateConfig) {
                // 通过回去布局方式自适应宽高
                int width = EstimateSpec.getSize(widthEstimateConfig);
                int height = EstimateSpec.getSize(heightEstimateConfig);

                setEstimatedSize(
                    EstimateSpec.getChildSizeWithMode(mSize, width, EstimateSpec.NOT_EXCEED),
                    EstimateSpec.getChildSizeWithMode(mSize, height, EstimateSpec.NOT_EXCEED)
                );
                return true;
            }
        });
        addDrawTask(new DrawTask() {
            @Override
            public void onDraw(Component component, Canvas canvas) {
                int saveCount = canvas.saveLayer(new RectFloat(0, 0, getWidth(), getHeight()), mPaint);
                drawLoading(canvas, mAnimateValue * DEGREE_PER_LINE);
                canvas.restoreToCount(saveCount);
            }
        });
    }

    private void initPaint() {
        mPaint = new Paint();
        mPaint.setColor(mPaintColor);
        mPaint.setAntiAlias(true);
        mPaint.setStrokeCap(Paint.StrokeCap.ROUND_CAP);
    }

    public void setColor(Color color) {
        mPaintColor = color;
        mPaint.setColor(color);
        invalidate();
    }

    public void setSize(int size) {
        mSize = size;
        postLayout();
    }

    private AnimatorValue.ValueUpdateListener mUpdateListener = new AnimatorValue.ValueUpdateListener() {
        @Override
        public void onUpdate(AnimatorValue animatorValue, float value) {
            mAnimateValue = (int) (value * 10);
            invalidate();
        }
    };

    public void start() {
        if (mAnimator == null) {
            mAnimator = new AnimatorValue();
            mAnimator.setValueUpdateListener(mUpdateListener);
            mAnimator.setDuration(600);
            mAnimator.setLoopedCount(AnimatorValue.INFINITE);
            mAnimator.setCurveType(Animator.CurveType.LINEAR);
            mAnimator.start();
        } else if (!mAnimator.isRunning()) {
            mAnimator.start();
        }
    }

    public void stop() {
        if (mAnimator != null) {
            mAnimator.setValueUpdateListener(null);
            mAnimator.cancel();
            mAnimator = null;
        }
    }

    private void drawLoading(Canvas canvas, int rotateDegrees) {
        int width = mSize / 12, height = mSize / 6;
        mPaint.setStrokeWidth(width);
        canvas.rotate(rotateDegrees, mSize / 2F, mSize / 2F);
        canvas.translate(mSize / 2F, mSize / 2F);
        for (int i = 0; i < LINE_COUNT; i++) {
            canvas.rotate(DEGREE_PER_LINE, 0, 0);
            float alpha = (255f * (i + 1) / LINE_COUNT);
            mPaint.setAlpha(alpha / 255);
            canvas.translate(0, -mSize / 2F + width / 2F);
            canvas.drawLine(new Point(0, 0), new Point(0, height), mPaint);
            canvas.translate(0, mSize / 2F - width / 2F);
        }
    }

    @Override
    public void onComponentBoundToWindow(Component component) {
        start();
    }

    @Override
    public void onComponentUnboundFromWindow(Component component) {
        stop();
    }
}
